#ifndef SDBM_H_INCLUDED
#define SDBM_H_INCLUDED

#include <boost/crc.hpp>
#include <boost/iostreams/filtering_stream.hpp> //filtering_stream
#include <boost/iostreams/filter/zlib.hpp>
#include <boost/iostreams/device/file.hpp> //file_sink
#include <boost/iostreams/device/file_descriptor.hpp>

#include <cryptopp/aes.h>
#include <cryptopp/rc6.h>
#include <cryptopp/base64.h>

#include <cryptopp/osrng.h>   //////AutoSeededRandomPool
#include <cryptopp/cryptlib.h>  /////CryptoPP::Exception
#include <cryptopp/filters.h>
#include <cryptopp/files.h>
#include <cryptopp/gcm.h>
#include <cryptopp/secblock.h>



#include <ctime>
#include <cstdlib>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <functional>   // std::bind

#include <unordered_map>
#include <regex>
#include <sstream>
#include <string>

#include <vector>

#include <thread>
#include <future>
#include <mutex>              // std::mutex, std::unique_lock
#include <condition_variable> // 全局条件变量

#ifdef SDBM_NAMESPACE
namespace SDBM_NAMESPACE {
#endif

using std::vector;
using std::string;
using std::unordered_map;
using std::unordered_multimap;

class DBM
{
public:
    struct db_info
    {
        char ltime[48];//最后修改时间
        unsigned int ltlen=0, row=0, col=0, coll=0,dbsize=0;/////最后修改时间长度//hash长度  ////行，列，最长列，总数据量
    };
    db_info info();
    bool opendb(const string&,bool log=true);//log :是否输出日志
    bool opendb(const string&,const string&,bool log=true);  //文件名 //字符编码   //日志
    bool opendb_c(const string&,const string&,bool log=true);//文件名 //密钥名 //输出日志
    bool opendb_c(const string&,const string&,const string&,bool log=true);
    void newdb(const string &FileName);
    bool write(const vector<string> &);//
    bool write(const string&);
    bool write(const string& ,const char);
    ///覆盖第idx条记录
    bool write(const vector<string> &, const unsigned int idx);
    bool write(const string& ,const unsigned int idx ,const char);
    ///插入到第idx条记录前
    bool insert(const vector<string> &, const unsigned int idx);
    bool insert(const string& ,const unsigned int idx ,const char);
    bool save();
    bool save_c();//加密保存，参数是密钥文件
    ///返回记录
    bool read(vector<string> & ,const unsigned int);
    bool read(string& ,const unsigned int);
    ///读取含有某字符的记录
    bool read(const string&, vector<vector<string>>&);
    bool read(const unsigned int ,const string&, vector<vector<string>>&);//读取在指定列含有某字符的记录

    bool find(const string &str, const char spilt, vector<vector<string>> &buf);
    ////find col
    bool del(const unsigned int);//删除记录
	bool setregex(const vector<bool> &buf);
	bool setnextline(const string&);
    void getregex(vector<bool>&);
    bool isopen();
    bool iflog();
    void iflog(bool);
    bool importdata(const string&,char);
    bool exportdata(const string&,char);
    bool importdata(const string&, const string&,char);
    bool exportdata(const string&, const string&,char);
    string GetLastErr();
    DBM(const string &);
    DBM();
    ~DBM();

 private:
    std::mutex _cv_mtx; // 全局互斥锁.
    std::condition_variable _cv_crc; // 全局条件变量.
    unsigned int _crc;// 全局crc变量,用于dbi与dbm之间互相保存.

    unordered_map <unsigned int, unordered_map<unsigned int, string>> kv_map;
    ///////             行^^^^^^                列^^^^^         值^^^^////////
    unordered_multimap <string, string> vi_map;
    //////             值^^^    行*列^^
    struct db_head
    {
        char cc[8];// ="sdb_map_1606";//sdb_idx_****
        char ltime[32];//最后修改时间
        char chline[16];
        unsigned int ltlen=0, chlen=0, row=0, col=0;////, col=0, coll=0,dbsize=0;/////最后修改时间长度//hash长度  ////行，列，最长列，总数据量
    };
    struct vi_head
    {
        char v[2048];//记录大于2048字节，查找换行符，按换行符分割记录
        char rc[16];//行 * 列
        unsigned int vl;//
    };
    struct key_value
    {
        unsigned int vl;
        char v[2048];////
    };
    string dbiErrStr,last_time,db_name,logname ,locode;
    //最后出错提示  //最后修改时间  //数据库名（不带后缀名）    //日志名    //本地字符编码，win：ASCII other:UTF-8
    string chline ="#"; //换行符
    bool _iflog=true;   ////    是否写日志   
    vector<bool>ifregex;
    ///是否使用正则表达式，当记录中有正则表达式符号时为false
    void clear();
    void _llog(const string&);
    //void __conf(const string&);
    void _wl(unsigned int level,const string&,const string&);
    void _wl(unsigned int level,const string&);
    inline void __wl(std::ostream &,unsigned int &,const string &msg1);
    bool _checkwrite(const vector<string> &);
    inline bool _checkwrite(const string &);
    void _dd(unsigned int);
    void _ww(const vector<string> &,const unsigned int);
    bool _ww(const string&,const unsigned int,const char);
    bool _cwl(const string&);
    void _rr(const string& str, vector<vector<string>>& buf);
    void _rre(const unsigned int ,const string &str, vector<vector<string>> &buf);
    inline void _rrc(const unsigned int col,const string &str, vector<vector<string>> &buf);
    void _rrid(vector<string> & ,const unsigned int);
    bool _ff(const string &str, const char,const unsigned int, const unsigned int, vector<vector<string>> &buf);
    bool _save1();
    bool _save2();
    bool _save_c1(const string&, const string&);
    bool _save_c2(const string&, const string&);
    void _snl(const string&);//设置换行符
    bool _open1(const string&);
    bool _open2();
    bool _openc1(const string&, const string&);//数据库名   //密钥名
    bool _openc2(const string&, const string&);//key //iv
    inline unsigned int getcol();
    inline unsigned int getcoll();
    void vi_kv();
    void kv_vi();
    void _dt0();////探测字符编码，自动调用dt1
    void _dt1(const string&);//编码转换
    void _dt2(const string&);
};
#ifdef SDBM_NAMESPACE
}
#endif

#endif // SDB_H_INCLUDED